﻿using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace MiniJson
{

public class JsonValue
{

    public static readonly int INVOID_LENGTH = -1;

    protected object value_;



    public static JsonValue Object()
    {
        JsonValue result = new JsonValue();
        return result;
    }

    public static JsonValue Array()
    {
        JsonValue result = new JsonValue(new List<JsonValue>());
        return result;
    }

    public JsonValue()
    {
        value_ = new Dictionary<string, JsonValue>();
    }

    public JsonValue(object value)
    {
        value_ = value;
    }

    public virtual System.Type GetValueType()
    {
        return value_.GetType();
    }

    public bool ContainsKey(string key)
    {
        Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;
        return m_val.ContainsKey(key);
    }

    public virtual JsonValue Get(string key)
    {
        if (!IsObject())
        {
            return JsonNull.GetInstance();
        }

        Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;

        if (!m_val.ContainsKey(key))
        {
            return JsonNull.GetInstance();
        }

        return m_val[key];

    }

    /// <summary>
    /// 转成模型 rgy
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T GetModel<T>() where T : new()
    {
        T model = new T();
        Type type = model.GetType();
        PropertyInfo[] pi = type.GetProperties();
        for (int i = 0; i < pi.Length; i++)
        {
            
            if (pi[i].PropertyType == typeof(List<int>))
            {
                List<int> list = new List<int>();
                for (int j = 0; j < this.Get(pi[i].Name).GetLength(); j++)
                {
                    list.Add(Get(pi[i].Name).GetInt(j));
                }
                pi[i].SetValue(model, list, null);
            }
            else if(pi[i].PropertyType == typeof(List<float>))
            {
                List<float> list = new List<float>();
                for (int j = 0; j < this.Get(pi[i].Name).GetLength(); j++)
                {
                    list.Add(Get(pi[i].Name).GetFloat(j));
                }
                pi[i].SetValue(model, list, null);
            }
            else if (pi[i].PropertyType == typeof(List<string>))
            {
                List<string> list = new List<string>();
                for (int j = 0; j < this.Get(pi[i].Name).GetLength(); j++)
                {
                    list.Add(Get(pi[i].Name).GetString(j));
                }
                pi[i].SetValue(model, list, null);
            }
            else
            {
                string value = this.GetString(pi[i].Name);
                if (string.IsNullOrEmpty(value))
                {
                    Debug.LogWarning(type.Name + ":Model JsonValue error: (" + pi[i].Name + ")");
                    continue;
                }
                pi[i].SetValue(model, Convert.ChangeType(value, pi[i].PropertyType), null);
            }
        }
        return model;
    }

    /// <summary>
    /// 转成模型 rgy
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T[] GetModels<T>() where T : new()
    {
        int modelLength = this.GetLength();
        var models = new T[modelLength];
        for (int i = 0; i < modelLength; i++)
        {
            JsonValue modelJson = this.Get(i);
            models[i] = modelJson.GetModel<T>();
        }
        return models;
    }

    public virtual JsonValue Get(int index)
    {
        if (!IsArray())
        {
            return null;
        }

        List<JsonValue> m_val = value_ as List<JsonValue>;
        return m_val[index];
    }

    public virtual string[] GetKeys()
    {
        if (!IsObject())
        {
            return null;
        }

        Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;

        string[] keys = new string[m_val.Count];

        int index = 0;
        foreach (string key in m_val.Keys)
        {
            keys[index] = key;
            ++index;
        }

        return keys;
    }

    public virtual int GetLength()
    {
        if (IsObject())
        {
            Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;
            return m_val.Count;
        }
        if (IsArray())
        {
            List<JsonValue> l_val = value_ as List<JsonValue>;
            return l_val.Count;
        }

        return INVOID_LENGTH;
    }

    public long GetLong(string key)
    {
        return Get(key).GetLong();
    }

    public long GetLong(int index)
    {
        return Get(index).GetLong();
    }

    public virtual long GetLong()
    {
        if (value_.GetType() != typeof(long))
        {
            return Convert.ToInt64(value_);
        }
        return (long)value_;
    }

    public int GetInt(string key)
    {
        return Get(key).GetInt();
    }

    public int GetInt(int index)
    {
        return Get(index).GetInt();
    }

    public virtual int GetInt()
    {
        if (value_.GetType() != typeof(int))
        {
            return Convert.ToInt32(value_);
        }
        return (int)value_;
    }

    public float GetFloat(string key)
    {
        return Get(key).GetFloat();
    }

    public float GetFloat(int index)
    {
        return Get(index).GetFloat();
    }

    public virtual float GetFloat()
    {
        if (value_.GetType() != typeof(float))
        {
            return Convert.ToSingle(value_);
        }
        return (float)value_;
    }

    public double GetDouble(string key)
    {
        return Get(key).GetDouble();
    }

    public double GetDouble(int index)
    {
        return Get(index).GetDouble();
    }

    public virtual double GetDouble()
    {
        if (value_.GetType() != typeof(double))
        {
            return Convert.ToDouble(value_);
        }
        return (double)value_;
    }

    public bool GetBoolean(string key)
    {
        return Get(key).GetBoolean();
    }

    public bool GetBoolean(int index)
    {
        return Get(index).GetBoolean();
    }

    public virtual bool GetBoolean()
    {
        return (bool)value_;
    }

    public string GetString(string key)
    {
        return Get(key).GetString();
    }

    public string GetString(int index)
    {
        return Get(index).GetString();
    }

    public virtual string GetString()
    {
        return value_.ToString();
    }

    public virtual bool IsNull()
    {
        if (value_ == null)
        {
            return true;
        }

        return false;
    }

    public virtual bool IsObject()
    {
        if (value_.GetType() == typeof(Dictionary<string, JsonValue>))
        {
            return true;
        }

        return false;
    }

    public virtual bool IsArray()
    {
        if (value_.GetType() == typeof(List<JsonValue>))
        {
            return true;
        }

        return false;
    }

    public override string ToString()
    {
        return value_.ToString();
    }

    public virtual JsonValue Add(JsonValue value)
    {
        if (!IsArray())
        {
            return this;
        }

        List<JsonValue> m_val = value_ as List<JsonValue>;
        m_val.Add(value);
        return this;
    }

    public virtual JsonValue Add(string value)
    {
        JsonValue val = new JsonValue(value);
        return Add(val);
    }

    public virtual JsonValue Add(long value)
    {
        JsonValue val = new JsonValue(value);
        return Add(val);
    }

    public virtual JsonValue Add(int value)
    {
        JsonValue val = new JsonValue(value);
        return Add(val);
    }

    public virtual JsonValue Add(double value)
    {
        JsonValue val = new JsonValue(value);
        return Add(val);
    }

    public virtual JsonValue Add(bool value)
    {
        JsonValue val = new JsonValue(value);
        return Add(val);
    }

    public virtual JsonValue Remove(string key)
    {
        if (!IsObject())
        {
            return this;
        }

        Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;
        if (m_val.ContainsKey(key))
        {
            m_val.Remove(key);
        }
        return this;
    }

    public virtual JsonValue Add(string key, JsonValue value)
    {
        if (!IsObject())
        {
            return this;
        }

        Dictionary<string, JsonValue> m_val = value_ as Dictionary<string, JsonValue>;

        if (m_val.ContainsKey(key))
        {
            m_val.Remove(key);
        }

        m_val.Add(key, value);
        return this;
    }

    public virtual JsonValue Add(string key, string value)
    {
        if (!IsObject())
        {
            return this;
        }

        JsonValue val = new JsonValue(value);
        return Add(key, val);
    }

    public virtual JsonValue Add(string key, long value)
    {
        if (!IsObject())
        {
            return this;
        }

        JsonValue val = new JsonValue(value);
        return Add(key, val);
    }

    public virtual JsonValue Add(string key, int value)
    {
        if (!IsObject())
        {
            return this;
        }

        JsonValue val = new JsonValue(value);
        return Add(key, val);
    }

    public virtual JsonValue Add(string key, double value)
    {
        if (!IsObject())
        {
            return this;
        }

        JsonValue val = new JsonValue(value);
        return Add(key, val);
    }

    public virtual JsonValue Add(string key, bool value)
    {
        if (!IsObject())
        {
            return this;
        }

        JsonValue val = new JsonValue(value);
        return Add(key, val);
    }

}

public class JsonNull : JsonValue
{

    private static JsonNull instance_;

    public static JsonNull GetInstance()
    {
        if (instance_ == null)
        {
            instance_ = new JsonNull();
        }
        return instance_;
    }

    public JsonNull()
    {
        value_ = null;
    }

    public override System.Type GetValueType()
    {
        return null;
    }

    public override JsonValue Get(string key)
    {
        return null;
    }

    public override JsonValue Get(int index)
    {
        return null;
    }

    public override string[] GetKeys()
    {
        return null;
    }

    public override int GetLength()
    {
        return 0;
    }

    public override long GetLong()
    {
        return 0;
    }

    public override int GetInt()
    {
        return 0;
    }

    public override float GetFloat()
    {
        return 0;
    }

    public override double GetDouble()
    {
        return 0;
    }

    public override bool GetBoolean()
    {
        return false;
    }

    public override string GetString()
    {
        return "";
    }

    public override bool IsNull()
    {
        return true;
    }

    public override bool IsObject()
    {
        return false;
    }

    public override bool IsArray()
    {
        return false;
    }

    public override string ToString()
    {
        return "";
    }

    public override JsonValue Add(JsonValue value)
    {
        return this;
    }

    public override JsonValue Add(string value)
    {
        return this;
    }

    public override JsonValue Add(long value)
    {
        return this;
    }

    public override JsonValue Add(int value)
    {
        return this;
    }

    public override JsonValue Add(double value)
    {
        return this;
    }

    public override JsonValue Add(bool value)
    {
        return this;
    }

    public override JsonValue Remove(string key)
    {
        return this;
    }

    public override JsonValue Add(string key, JsonValue value)
    {
        return this;
    }

    public override JsonValue Add(string key, string value)
    {
        return this;
    }

    public override JsonValue Add(string key, long value)
    {
        return this;
    }

    public override JsonValue Add(string key, int value)
    {
        return this;
    }

    public override JsonValue Add(string key, double value)
    {
        return this;
    }

    public override JsonValue Add(string key, bool value)
    {
        return this;
    }

}



}